import {Injectable, BadRequestException, Inject} from '@nestjs/common';
import {InjectEntityManager} from '@nestjs/typeorm';
import {EntityManager, Like, Between} from 'typeorm';
import {Meeting} from 'src/meeting/entities/meeting.entity';
import {User} from 'src/user/entities/user.entity';
import {Booking} from 'src/booking/entities/booking.entity';
import {CreateBookingDto} from './dto/create-booking.dto';
import {RedisService} from 'src/middleware/redis/redis.service';
import {EmailService} from '../middleware/email/email.service';
import {ExamineBookingDto} from "./dto/examine-booking.dto";

@Injectable()
export class BookingService {
    @InjectEntityManager()
    private entityManager: EntityManager;
    @Inject(RedisService)
    private redisService: RedisService;

    @Inject(EmailService)
    private emailService: EmailService;

    // 插入数据
    async initData() {
        const user1 = await this.entityManager.findOneBy(User, {
            id: 1,
        });
        const user2 = await this.entityManager.findOneBy(User, {
            id: 2,
        });

        const room1 = await this.entityManager.findOneBy(Meeting, {
            id: 1,
        });
        const room2 = await await this.entityManager.findOneBy(Meeting, {
            id: 2,
        });

        const booking1 = new Booking();
        booking1.room = room1;
        booking1.user = user1;
        booking1.startTime = new Date();
        booking1.endTime = new Date(Date.now() + 1000 * 60 * 60);

        await this.entityManager.save(Booking, booking1);

        const booking2 = new Booking();
        booking2.room = room2;
        booking2.user = user2;
        booking2.startTime = new Date();
        booking2.endTime = new Date(Date.now() + 1000 * 60 * 60);

        await this.entityManager.save(Booking, booking2);

        const booking3 = new Booking();
        booking3.room = room1;
        booking3.user = user2;
        booking3.startTime = new Date();
        booking3.endTime = new Date(Date.now() + 1000 * 60 * 60);

        await this.entityManager.save(Booking, booking3);

        const booking4 = new Booking();
        booking4.room = room2;
        booking4.user = user1;
        booking4.startTime = new Date();
        booking4.endTime = new Date(Date.now() + 1000 * 60 * 60);

        await this.entityManager.save(Booking, booking4);
    }

    async findAll(
        pageNum: number,
        pageSize: number,
        username: string,
        meetingName: string,
        meetingPosition: string,
        bookingTimeRangeStart: number,
        bookingTimeRangeEnd: number,
    ) {
        const skipCount = (pageNum - 1) * pageSize;

        const condition: Record<string, any> = {};

        if (username) {
            condition.user = {
                username: Like(`%${username}%`),
            };
        }

        if (meetingName) {
            condition.room = {
                name: Like(`%${meetingName}%`),
            };
        }

        if (meetingPosition) {
            if (!condition.room) {
                condition.room = {};
            }
            condition.room.location = Like(`%${meetingPosition}%`);
        }

        if (bookingTimeRangeStart) {
            if (!bookingTimeRangeEnd) {
                bookingTimeRangeEnd = bookingTimeRangeStart + 60 * 60 * 1000;
            }
            condition.startTime = Between(
                new Date(bookingTimeRangeStart),
                new Date(bookingTimeRangeEnd),
            );
        }

        const [bookings, total] = await this.entityManager.findAndCount(Booking, {
            where: condition,
            relations: {
                user: true,
                room: true,
            },
            skip: skipCount,
            take: pageSize,
        });

        return {
            bookings: bookings.map((item) => {
                delete item.user.password;
                return item;
            }),
            pageNum,
            pageSize,
            total,
        };
    }

    async create(bookingDto: CreateBookingDto, userId: number) {
        const meeting = await this.entityManager.findOneBy(Meeting, {
            id: Number(bookingDto.meetingId),
        });

        if (!meeting) {
            throw new BadRequestException('会议室不存在');
        }

        const user = await this.entityManager.findOneBy(User, {
            id: userId,
        });

        const booking = new Booking();
        booking.room = meeting;
        booking.user = user;
        booking.startTime = new Date(bookingDto.startTime);
        booking.endTime = new Date(bookingDto.endTime);
        booking.note = bookingDto.note
        meeting.isBooked = true

        const res = await this.entityManager.findOneBy(Booking, {
            room: {
                id: meeting.id,
            },
        });
        // 同一时段不能预约功能未实现
        // startTime: LessThanOrEqual(booking.startTime),
        // endTime: MoreThanOrEqual(booking.endTime),
        // LessThanOrEqual,MoreThanOrEqual, 在 typeorm 引入

        if (res) {
            console.log(res, 'res')
            if (res.status !== '已解除') {
                throw new BadRequestException('该会议室已经预定');
            }
        }
        await this.entityManager.save(Meeting, meeting);
        await this.entityManager.save(Booking, booking);
    }

    async apply(id: number) {
        await this.entityManager.update(
            Booking,
            {
                id,
            },
            {
                status: '审批通过',
            },
        );
        return 'success';
    }

    async reject(id: number) {
        await this.entityManager.update(
            Booking,
            {
                id,
            },
            {
                status: '审批驳回',
            },
        );
        return 'success';
    }

    async unbind(id: number) {
        await this.entityManager.update(
            Booking,
            {
                id,
            },
            {
                status: '已解除',
            },
        );
        return 'success';
    }

    async urge(id: number) {
        const flag = await this.redisService.get('urge_' + id);

        if (flag) {
            return '半小时内只能催办一次，请耐心等待';
        }

        let email = await this.redisService.get('admin_email');

        if (!email) {
            const admin = await this.entityManager.findOne(User, {
                select: {
                    email: true,
                },
                where: {
                    isAdmin: true,
                },
            });

            email = admin.email;

            this.redisService.set('admin_email', admin.email);
        }

        this.emailService.sendMail({
            to: email,
            subject: '预定申请催办提醒',
            html: `id 为 ${id} 的预定申请正在等待审批`,
        });

        this.redisService.set('urge_' + id, 1, 60 * 30);
    }

    async examineBooking(examine: ExamineBookingDto) {
        const booking = await this.entityManager.findOneBy(Booking, {
            id: Number(examine.id),
        })
        if (examine.status) {
            booking.status = "审批通过"
        } else {
            booking.status = "审批驳回"
        }
        await this.entityManager.save(booking)
    }
}
